import './index.css'
import * as THREE from 'three'
import {
    GLTFLoader
} from 'three/examples/jsm/Addons.js'
import {
    OrbitControls
} from 'three/examples/jsm/controls/OrbitControls'
import {
    gsap
} from 'gsap'


/**
 * Size
 */
const Size = {
    width: window.innerWidth,
    height: window.innerHeight
}


/**
 * Camera
 */
const camera = new THREE.PerspectiveCamera(75, Size.width / Size.height, 0.1, 100)
camera.position.set(10, 15, 10)

/**
 * Scene
 */
const scene = new THREE.Scene()





/**
 * Light
 */
const ambientLight = new THREE.AmbientLight(new THREE.Color('#ffffff'), 3)
scene.add(ambientLight)

/**
 * overlay
 */
// 创建一个平面
const overlayGeometry = new THREE.PlaneGeometry(2, 2, 1, 1)
const overlayMaterial = new THREE.ShaderMaterial({
    // wireframe:true,
    transparent: true,
    uniforms: {
        uAlpha: {
            value: 1.0
        }
    },
    vertexShader: `
       void main(){
          gl_Position = vec4(position,1.0);
       }
    `,
    fragmentShader: `
       uniform float uAlpha;
       void main(){
          gl_FragColor = vec4(0.0,0.0,0.0,uAlpha);
       }
    `
})
const overlay = new THREE.Mesh(overlayGeometry, overlayMaterial)
scene.add(overlay)

/**
 * Loader
 */
//loading
const loadingBarElement = document.querySelector('.loading-bar')
const loadingManger = new THREE.LoadingManager(
    // loaded
    () => {
       window.setTimeout(()=>{
        gsap.to(overlayMaterial.uniforms.uAlpha,{duration:3, value:0 })
        loadingBarElement.classList.add('ended')
        loadingBarElement.style.transform = ''
       },500) 
    },
    // progress
    (itemUrl,itemsLoaded,itemsTotal) => {
      const progressRatio = itemsLoaded / itemsTotal
      loadingBarElement.style.transform = `scaleX(${progressRatio})`
    }
)
const cubeTextureLoader = new THREE.CubeTextureLoader(loadingManger)
const loader = new GLTFLoader(loadingManger);


/**
 * Model
 */
loader.load('../assets/models/su7/scene.gltf',
    function (gltf) {
        console.log('success')
        gltf.scene.scale.set(5, 5, 5)
        gltf.scene.castShadow = true
        scene.add(gltf.scene)
        updateAllMaterials()
    },
    function (progress) {
        console.log('progress')
    },
    function (error) {
        console.log('error')
        console.log(error)
    },
)





/**
 * Renderer
 */
const canvas = document.querySelector('canvas.webgl')
const renderer = new THREE.WebGLRenderer({
    canvas,
    antialias: true,
})
renderer.setSize(Size.width, Size.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.setClearColor(0x000000, 1)
// 物理上正确的光照模式
renderer.physicallyCorrectLights = true
// outputEncoding 渲染器的输出编码
renderer.outputEncoding = THREE.sRGBEncoding
//toneMappingExposure 色调映射的曝光级别
renderer.toneMappingExposure = 2.5
// shadow
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap



/**
 * Environment map
 */
const environmentMap = cubeTextureLoader.load([
    '../assets/textures/environmentMaps/0/px.jpg',
    '../assets/textures/environmentMaps/0/nx.jpg',
    '../assets/textures/environmentMaps/0/py.jpg',
    '../assets/textures/environmentMaps/0/ny.jpg',
    '../assets/textures/environmentMaps/0/pz.jpg',
    '../assets/textures/environmentMaps/0/nz.jpg',
])
environmentMap.encoding = THREE.sRGBEncoding
scene.background = environmentMap


/**
 * 优化材质
 */
const updateAllMaterials = () => {
    scene.traverse((child) => {
        if (child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) {
            // console.log(child)
            //遍历模型中的 Mesh，并添加材质的环境贴图，将环境贴图强度设置为 2.5
            child.material.envMap = environmentMap
            child.material.envMapIntensity = 2.5
            // 开启阴影
            child.castShadow = true
            child.receiveShadow = true
        }
    })
}


/**
 * OrbitControls
 */
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true


/**
 * Update
 */
const clock = new THREE.Clock()
const tick = () => {
    const elpasedTime = clock.getElapsedTime()
    controls.update();
    renderer.render(scene, camera)
    requestAnimationFrame(tick)
}
tick()


/**
 * resize
 */
window.addEventListener('resize', () => {
    Size.width = window.innerWidth
    Size.height = window.innerHeight

    camera.aspect = Size.width / Size.height
    camera.updateProjectionMatrix()

    renderer.setSize(Size.width, Size.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})